From 5e302ae2cc62d2e1d7cae9e6efb3b32b368c7b30 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 17 Jan 2018 20:15:45 -0500 Subject: [PATCH] Add a way to release GL resources The inspector may hold on to render nodes and textures beyond the lifetime of the widget (and thus the GL resources). To handle this situation, allow the widget to explicitly release the GL resources, and make the texture available on the clent-side as a cairo surface. This lets the recorder still show the content after the widget is gone. --- gdk/gdktexture.c | 72 ++++++++++++++++++++++++++++++++++++++++++++---- gdk/gdktexture.h | 3 ++ 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c index c87ed57a1d..f85b096ec0 100644 --- a/gdk/gdktexture.c +++ b/gdk/gdktexture.c @@ -443,6 +443,8 @@ struct _GdkGLTexture { GdkGLContext *context; int id; + cairo_surface_t *saved; + GDestroyNotify destroy; gpointer data; }; @@ -458,10 +460,21 @@ gdk_gl_texture_dispose (GObject *object) { GdkGLTexture *self = GDK_GL_TEXTURE (object); - g_object_unref (self->context); - if (self->destroy) - self->destroy (self->data); + { + self->destroy (self->data); + self->destroy = NULL; + self->data = NULL; + } + + g_clear_object (&self->context); + self->id = 0; + + if (self->saved) + { + cairo_surface_destroy (self->saved); + self->saved = NULL; + } G_OBJECT_CLASS (gdk_gl_texture_parent_class)->dispose (object); } @@ -474,7 +487,6 @@ gdk_gl_texture_download (GdkTexture *texture, GdkGLTexture *self = GDK_GL_TEXTURE (texture); cairo_surface_t *surface; cairo_t *cr; - GdkWindow *window; surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, @@ -482,8 +494,21 @@ gdk_gl_texture_download (GdkTexture *texture, stride); cr = cairo_create (surface); - window = gdk_gl_context_get_window (self->context); - gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0, texture->width, texture->height); + + if (self->saved) + { + cairo_set_source_surface (cr, self->saved, 0, 0); + cairo_paint (cr); + } + else + { + GdkWindow *window; + + window = gdk_gl_context_get_window (self->context); + gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0, + texture->width, texture->height); + } + cairo_destroy (cr); cairo_surface_finish (surface); cairo_surface_destroy (surface); @@ -516,6 +541,41 @@ gdk_gl_texture_get_id (GdkGLTexture *self) return self->id; } +void +gdk_texture_release_gl (GdkTexture *texture) +{ + GdkGLTexture *self; + GdkWindow *window; + cairo_t *cr; + + g_return_if_fail (GDK_IS_GL_TEXTURE (texture)); + + self = GDK_GL_TEXTURE (texture); + + g_return_if_fail (self->saved == NULL); + + self->saved = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + texture->width, texture->height); + + cr = cairo_create (self->saved); + + window = gdk_gl_context_get_window (self->context); + gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0, + texture->width, texture->height); + + cairo_destroy (cr); + + if (self->destroy) + { + self->destroy (self->data); + self->destroy = NULL; + self->data = NULL; + } + + g_clear_object (&self->context); + self->id = 0; +} + /** * gdk_texture_new_for_pixbuf: * @pixbuf: a #GdkPixbuf diff --git a/gdk/gdktexture.h b/gdk/gdktexture.h index 4f3ead2321..ae7ac812f2 100644 --- a/gdk/gdktexture.h +++ b/gdk/gdktexture.h @@ -64,6 +64,9 @@ GdkTexture * gdk_texture_new_for_gl (GdkGLContext GDestroyNotify destroy, gpointer data); +GDK_AVAILABLE_IN_3_94 +void gdk_texture_release_gl (GdkTexture *texture); + GDK_AVAILABLE_IN_3_94 int gdk_texture_get_width (GdkTexture *texture); GDK_AVAILABLE_IN_3_94 -- 2.30.2